<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Reactive web component example with subclassing</title>

    <template id="incrementDecrementTemplate">
      <button id="decrement">-</button>
      <span id="visibleValue"></span>
      <button id="increment">+</button>
    </template>

    <script type="module">
      import {
        defaultState,
        firstRender,
        ids,
        render,
        setState,
        state,
        template,
      } from "../src/base/internal.js";
      import { templateFrom } from "../src/core/htmlLiterals.js";
      import {
        createElement,
        replace,
        transmute,
      } from "../src/core/template.js";
      import ReactiveElement from "../src/core/ReactiveElement.js";

      class IncrementDecrement extends ReactiveElement {
        // This property becomes the value of this[state] at constructor time.
        get [defaultState]() {
          return Object.assign(super[defaultState], {
            value: 0,
          });
        }

        // When state changes, render updates to the DOM.
        [render](changed) {
          super[render](changed);

          if (this[firstRender]) {
            this[ids].decrement.addEventListener("click", () => {
              this.value--;
            });
            this[ids].increment.addEventListener("click", () => {
              this.value++;
            });
          }

          if (changed.value) {
            const { value } = this[state];
            this.style.color = value < 0 ? "red" : null;
            this[ids].visibleValue.textContent = value;
          }
        }

        get [template]() {
          return incrementDecrementTemplate;
        }

        // Provide a public property that gets/sets state.
        get value() {
          return this[state].value;
        }
        set value(value) {
          this[setState]({
            value: parseInt(value),
          });
        }
      }

      customElements.define("increment-decrement", IncrementDecrement);

      class CustomIncrementDecrement extends IncrementDecrement {
        get [template]() {
          const result = super[template];
          result.content.append(
            templateFrom.html`
              <style>
                :host {
                  background: lightgray;
                  font-family: Helvetica, Arial, sans-serif;
                  font-weight: bold;
                }

                button {
                  background: #444;
                  border: none;
                  border-radius: 0;
                  color: white;
                }

                button:disabled {
                  color: gray;
                }
              </style>
            `.content
          );
          return result;
        }

        [render](changed) {
          super[render](changed);
          if (changed.value) {
            const { value } = this[state];
            if (value > 0) {
              this.style.color = "dodgerblue";
            }
            this[ids].decrement.disabled = value <= -5;
            this[ids].increment.disabled = value >= 5;
          }
        }

        get value() {
          return super.value;
        }
        set value(value) {
          // Enforce a bound of -5 to 5 on the value.
          const parsed = parseInt(value);
          const bounded = Math.max(Math.min(parsed, 5), -5);
          super.value = bounded;
        }
      }

      customElements.define(
        "custom-increment-decrement",
        CustomIncrementDecrement
      );
    </script>
  </head>

  <body>
    <p>
      This shows a plain increment/decrement component and a subclass with
      styling and custom behavior.
    </p>
    <increment-decrement></increment-decrement>
    <custom-increment-decrement></custom-increment-decrement>
  </body>
</html>
